// log_manager.cpp
#include "log_manager.h"
#include <sys/stat.h>
#include <dirent.h>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <iostream>
#include <vector>
#include <algorithm>

LoggerManager::LoggerManager(const std::string& log_dir,
                             const std::string& file_prefix,
                             int retention_days)
    : log_directory_(log_dir), file_prefix_(file_prefix), retention_days_(retention_days) {

    // 初始化日志目录
    initializeLogDirectory();

    // 清理旧日志文件
    cleanupOldLogFiles(retention_days_);

    try {
        // 创建控制台日志记录器
        auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
        console_sink->set_level(spdlog::level::debug);

        // 为控制台sink单独设置格式，包含函数名
        console_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%s:%#] [%!] %v");

        // 创建带时间戳的文件名
        auto timestamp = getCurrentTimestamp();
        std::string log_filename = log_directory_ + "/" + file_prefix_ + "_" + timestamp + ".log";

        // 创建文件日志记录器
        auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(log_filename, true);
        file_sink->set_level(spdlog::level::debug);

        // 为文件sink单独设置格式，包含函数名
        file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%s:%#] [%!] %v");

        // 创建多sink记录器
        std::vector<spdlog::sink_ptr> sinks {console_sink, file_sink};

        // 使用应用程序名称作为记录器名称
        logger_ = std::make_shared<spdlog::logger>("robot_logs_server", sinks.begin(), sinks.end());

        logger_->set_level(spdlog::level::debug);
        logger_->flush_on(spdlog::level::debug);

        // 设置全局默认记录器
        spdlog::set_default_logger(logger_);
        spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%s:%#] [%!] %v");

        // 使用新格式记录初始化信息
        SPDLOG_INFO("LoggerManager 初始化完成");
        SPDLOG_INFO("日志文件: {}", log_filename);
        SPDLOG_INFO("日志保留天数: {}天", retention_days_);
    } catch (const spdlog::spdlog_ex& ex) {
        std::cout << "Spdlog 初始化失败: " << ex.what() << std::endl;
    }
}

void LoggerManager::initializeLogDirectory() {
    // 检查日志目录是否存在，不存在则创建
    struct stat info;
    if (stat(log_directory_.c_str(), &info) != 0) {
        // 目录不存在，创建目录
#ifdef _WIN32
        int status = mkdir(log_directory_.c_str());
#else
        int status = mkdir(log_directory_.c_str(), 0755);
#endif
        if (status == 0) {
            std::cout << "创建日志目录: " << log_directory_ << std::endl;
        } else {
            std::cout << "创建日志目录失败" << std::endl;
        }
    } else if (info.st_mode & S_IFDIR) {
        // 目录已存在
        std::cout << "日志目录已存在: " << log_directory_ << std::endl;
    } else {
        // 存在同名文件而非目录
        std::cout << "存在同名文件，无法创建日志目录" << std::endl;
    }
}

void LoggerManager::cleanupOldLogFiles(int days) {
    // 获取指定天数前的时间戳
    auto now = std::chrono::system_clock::now();
    auto days_ago = now - std::chrono::hours(24 * days);

    DIR* dir;
    struct dirent* ent;
    if ((dir = opendir(log_directory_.c_str())) != nullptr) {
        int deleted_count = 0;
        while ((ent = readdir(dir)) != nullptr) {
            std::string filename = ent->d_name;
            // 检查是否为当前前缀的日志文件
            if (filename.find(file_prefix_ + "_") != std::string::npos &&
                filename.find(".log") != std::string::npos) {
                // 提取时间戳部分
                size_t start_pos = filename.find(file_prefix_ + "_") + file_prefix_.length() + 1;
                size_t end_pos = filename.find(".log");
                if (end_pos > start_pos) {
                    std::string timestamp_str = filename.substr(start_pos, end_pos - start_pos);
                    // 解析时间戳并比较
                    if (isOlderThanDays(timestamp_str, days_ago)) {
                        std::string full_path = log_directory_ + "/" + filename;
                        if (remove(full_path.c_str()) == 0) {
                            std::cout << "删除旧日志文件: " << full_path << std::endl;
                            deleted_count++;
                        } else {
                            std::cout << "删除旧日志文件失败: " << full_path << std::endl;
                        }
                    }
                }
            }
        }
        closedir(dir);
        std::cout << "共删除 " << deleted_count << " 个旧日志文件" << std::endl;
    }
}

bool LoggerManager::isOlderThanDays(const std::string& timestamp_str,
                                   std::chrono::system_clock::time_point days_ago) {
    // 解析时间戳格式: YYYYMMDD_HHMMSS
    if (timestamp_str.length() != 15) return false;

    try {
        int year = std::stoi(timestamp_str.substr(0, 4));
        int month = std::stoi(timestamp_str.substr(4, 2));
        int day = std::stoi(timestamp_str.substr(6, 2));
        int hour = std::stoi(timestamp_str.substr(9, 2));
        int minute = std::stoi(timestamp_str.substr(11, 2));
        int second = std::stoi(timestamp_str.substr(13, 2));

        // 构造时间点
        std::tm timeinfo = {};
        timeinfo.tm_year = year - 1900;
        timeinfo.tm_mon = month - 1;
        timeinfo.tm_mday = day;
        timeinfo.tm_hour = hour;
        timeinfo.tm_min = minute;
        timeinfo.tm_sec = second;

        std::time_t file_time = std::mktime(&timeinfo);
        auto file_time_point = std::chrono::system_clock::from_time_t(file_time);

        return file_time_point < days_ago;
    } catch (...) {
        return false;
    }
}

std::string LoggerManager::getCurrentTimestamp() {
    auto now = std::chrono::system_clock::now();
    auto time_t = std::chrono::system_clock::to_time_t(now);

    std::ostringstream oss;
    oss << std::put_time(std::localtime(&time_t), "%Y%m%d_%H%M%S");
    return oss.str();
}

void LoggerManager::setLogLevel(spdlog::level::level_enum level) {
    if (logger_) {
        logger_->set_level(level);
        logger_->flush_on(level);
    }
}
